package com.qq.多线程.线程池;



import java.util.concurrent.*;

/*
	java.util.concurrent.Executors 
    concurrent:并发包，多线程是并发的概念，所以多线程技术都在该并发包下。
  
	Executors：
	线程池的工具类，通过调用方法返回不同类型的线程池对象。
	注：底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。
 	其实就是预设好了参数的ThreadPoolExecutor线程池，我们直接调用方法就能使用。
 	
	Executors得到线程池对象的常用方法：(工具类一般都是静态方法，方便我们调用)
	 无限线程的线程池：
	1.public static ExecutorService newCachedThreadPool()
	    核心线程为：0  任务队列为：SynchronousQueue<Runnable>() 无任务队列
	    最大线程数量为 ：Integer.MAX_VALUE 无限制
	    所以临时线程随着任务增加而增加。
	    但不会多少个任务就多少个线程，因为线程执行完任务会存活60S，此时还能执行其他任务，
	    只有空闲60S才会被回收。
	    但同时处理大量任务时，也会同时创建大量线程，可能会内存溢出 java.lang.OutOfMemoryError 堆内存溢出
	    
	2.public static ScheduledExecutorService newScheduledThreadPool​(int corePoolSize)
	    创建一个线程池，可以实现在给定的延迟后运行任务，或者定期执行任务。 临时线程存活10毫秒 
	    限制了核心线程数量，没有限制最大线程数量 MAX.VALUE无穷大，且临时线程执行完任务后立刻回收，
	    同时处理大量任务时，也会同时创建大量线程，可能会内存溢出 java.lang.OutOfMemoryError 
	    
	  无限队列的线程池：
	3.public static ExecutorService newFixedThreadPool​(int nThreads)
	    核心线程和最大线程数相同，所以不创建临时线程，只有核心线程。
	    任务队列为：LinkedBlockingQueue<Runnable>()——Integer.MAX_VALUE 可无限排。
	    创建固定线程数量的线程池，如果某个核心线程因为执行异常而结束，那么线程池会补充一个新线程替代它。
	    但处理大量任务时，因为任务队列无限排，会堆积大量任务请求，可能会内存溢出 java.lang.OutOfMemoryError 
	
	4.public static ExecutorService newSingleThreadExecutor ()
	    创建只有一个核心线程的线程池对象，如果该线程出现异常而结束，那么线程池会补充一个新线程。
	    和newFixedThreadPool原理一样，
	    处理大量任务时，因为任务队列无限排，会堆积大量任务请求，可能出现内存溢出。
	
 	注意：
	大型并发系统环境(京东、淘宝)中使用Executors如果不注意可能会出现系统风险
	出现OOM错误java.lang.OutOfMemoryError————内存溢出
	所以Executors工具类不适合做大型互联网场景的线程池方案。
	建议使用ThreadPoolExecutor来指定线程池参数，这样可以明确线程池的运行规则，规避资源耗尽的风险。
	五六十个人，几百个人，使用Executors没问题

    目标：使用Executors的工具方法直接得到线程池对象。
 */
public class ThreadPool_Test3 {
    public static void main(String[] args) throws Exception {
        // 1、创建固定线程的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable());
        pool.execute(new MyRunnable()); //已经没有多余线程了，只能等核心线程执行完任务
        
        //2、创建随任务增加线程的线程池
        ExecutorService pool2 = Executors.newCachedThreadPool();
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable()); 
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable());
        pool2.execute(new MyRunnable()); //8个临时线程
        
    }
}
